<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet 
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
	xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	xmlns:ccts="urn:un:unece:uncefact:documentation:standard:CoreComponentsTechnicalSpecification:2"
	xmlns:ebfuncs="http://code.google.com/p/eb-forms/functions"
	version="2.0">
	
	<xsl:import href="GlobalVars.xsl"/>
	<xsl:import href="GlobalTemplates.xsl"/>
	<xsl:import href="GlobalFunctions.xsl"/>
	
	<xsl:variable name="global.element.types.used">
		<xsl:call-template name="BuildTypelist" >
			<xsl:with-param name="element.root" 
				select="$global.doc.schema.root/xsd:schema/xsd:element/@name" />
			<xsl:with-param name="element.root.type" 
				select="$global.doc.schema.root/xsd:schema/xsd:element/@type" />
		</xsl:call-template>
	</xsl:variable>
	
	<xsl:template name="BuildTypelist">
		<xsl:param name="element.root" as="xsd:string" required="yes"/>
		<xsl:param name="element.root.type" as="xsd:string" required="yes"/>
		
		<xsl:variable name="types">
			<xsl:call-template name="GetElementTypes">
				<xsl:with-param name="element.type" select="$element.root.type" />
				<xsl:with-param name="element.schema" 
					select="document-uri( $global.doc.schema.root )" />
			</xsl:call-template>
		</xsl:variable>
		
		<xsl:variable name="codelistTypes">
			<xsl:call-template name="GetCodelistTypes">
				<xsl:with-param name="types.used" select="$types/type[not( @name = preceding-sibling::type/@name)]" />
			</xsl:call-template>
		</xsl:variable>

		<!-- Filter out all double types and codelistTypes -->
		<xsl:sequence select="$types/type[not( @name = preceding-sibling::type/@name)]" />
		<xsl:element name="codelistTypes">
			<xsl:copy-of select="$codelistTypes/count" />
			<xsl:copy-of 
				select="$codelistTypes/attribute[not( @name = preceding-sibling::attribute/@name
				and @type = preceding-sibling::attribute/@type)]" />
		</xsl:element>
	</xsl:template>
	
	<xsl:template name="GetElementTypes">
		<xsl:param name="element.type" as="xsd:string" required="yes" />
		<xsl:param name="element.schema" as="xsd:string" required="yes" />
		
		<xsl:variable name="element.children">
			<xsl:call-template name="GetChildElements">
				<xsl:with-param name="parent" select="substring-after( $element.type, ':' )" />
				<xsl:with-param name="parent.schema" select="$element.schema" />
			</xsl:call-template>			
		</xsl:variable>
		
		<xsl:for-each select="$element.children/xsd:element">
			<xsl:choose>
				<xsl:when test="ebfuncs:getAcronym( . ) = 'BBIE' ">
					<xsl:variable name="element.type.schema">
						<xsl:call-template name="GetDataTypeDocument">
							<xsl:with-param name="element.type" select="@type" />
							<xsl:with-param name="element.schema" select="$element.schema" />
						</xsl:call-template>
					</xsl:variable>
					<xsl:element name="type">
						<xsl:attribute name="name" select="@type" />
						<xsl:attribute name="schema" select="$element.type.schema" />
					</xsl:element>
				</xsl:when>
				<xsl:otherwise>
					<xsl:variable name="element.child.ns" 
						select="namespace-uri-for-prefix( substring-before( @type, ':' ), . )"/>
					<xsl:variable name="element.ns" select="if( $element.schema = '' ) 
						then $global.doc.schema.root/xsd:schema/@targetNamespace
						else document( $element.schema )/xsd:schema/@targetNamespace"/>
					<xsl:choose>
						<!-- 
							Test if the child element is declared in the same namespace as it's parent. If not then
							we'll have to look in which document the namespace (and thus the element) is declared.
							Also we'll have to look which prefix is used for that namespace.
						-->
						<xsl:when test="$element.ns != $element.child.ns">
							<xsl:variable name="element.type.schema" as="xsd:string">
								<xsl:call-template name="GetDataTypeDocument">
									<xsl:with-param name="element.type" select="@type" />
									<xsl:with-param name="element.schema" select="$element.schema" />
								</xsl:call-template>
							</xsl:variable>
							
							<xsl:call-template name="GetElementTypes">
								<xsl:with-param name="element.type" select="@type"/>
								<xsl:with-param name="element.schema" select="$element.type.schema" />
							</xsl:call-template>
						</xsl:when>
						<!-- 
							The element is declared in the same document as his parent.
						-->
						<xsl:otherwise>
							<xsl:call-template name="GetElementTypes">
								<xsl:with-param name="element.type" select="@type"/>
								<xsl:with-param name="element.schema" select="$element.schema" />
							</xsl:call-template>
						</xsl:otherwise>
					</xsl:choose>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:for-each>
	</xsl:template>
	
	<xsl:template name="GetCodelistTypes">
		<xsl:param name="types.used" as="item()*" required="yes" />
		
		<xsl:for-each select="$types.used">
			<xsl:variable name="element.type.simple" as="xsd:boolean" >
				<xsl:call-template name="BasedOnSimpleType">
					<xsl:with-param name="element.type" select="@name" />
					<xsl:with-param name="element.type.schema" select="@schema" />
				</xsl:call-template>
			</xsl:variable>
			
			<xsl:choose>
				<xsl:when test="$element.type.simple and contains( @name, 'qdt' )">
					<xsl:variable name="type.name" select="substring-after( @name, ':' )" />
					<xsl:variable name="list.content.type" 
						select="document( @schema )/xsd:schema/xsd:simpleType[@name = $type.name]/xsd:restriction/@base" />
					<xsl:variable name="list.content.type.schema" >
						<xsl:call-template name="GetDataTypeDocument">
							<xsl:with-param name="element.type" select= "$list.content.type" />
							<xsl:with-param name="element.schema" select="@schema" />
						</xsl:call-template>
					</xsl:variable>
					<!--
						This is not realy an attribute but and CodeType or IDType which is directly based on
						some content type. This makes the type less or more an attribute itself.
					-->
					<xsl:element name="attribute">
						<xsl:attribute name="name" select="@name" />
						<xsl:attribute name="type" select="$list.content.type" />
						<xsl:attribute name="type.schema" select="$list.content.type.schema" />
					</xsl:element>
				</xsl:when>
				<xsl:otherwise>
					<xsl:variable name="type" select="@name" />
					<xsl:variable name="type.schema" select="@schema" />
					
					<xsl:variable name="type.attributes.used">
						<xsl:call-template name="GetAttributes">
							<xsl:with-param name="type" select="$type" />
							<xsl:with-param name="type.schema" select="$type.schema" />
						</xsl:call-template>
					</xsl:variable>
					
					<xsl:for-each select="$type.attributes.used/attribute">
						<xsl:variable name="type.attribute.info">
							<xsl:call-template name="GetAttributeInfo">
								<xsl:with-param name="type" select="$type" />
								<xsl:with-param name="type.schema" select="$type.schema" />
								<xsl:with-param name="type.attribute" select="@name" />
							</xsl:call-template>
						</xsl:variable>
						<!--
							For now we asume that if a type has a schema it's a codelist type. This
							is at all not secure and should be changed!
						-->
						<xsl:if test="not( $type.attribute.info/attribute/@type.schema = '' )">
							<xsl:sequence select="$type.attribute.info" />
						</xsl:if>
					</xsl:for-each>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:for-each>
	</xsl:template>
</xsl:stylesheet>
